多态能够增强程序的可扩充性

在面向对象的程序设计中使用「多态」,能够增强程序的可扩充性,即程序需要修改或增加功能的时候,需要改动和增加的代码较少 。

下面我们用设计 LOL 英雄联盟游戏的英雄的例子,说明多态为什么可以在修改或增加功能的时候,可以较少的改动代码。

LOL 英雄联盟是 5v5 竞技游戏,游戏中有很多英雄,每种英雄都有一个「类」与之对应,每个英雄就是一个「对象」。

英雄之间能够互相攻击,攻击敌人和被攻击时都有相应的动作,动作是通过对象的成员函数实现的。

下面挑了五个英雄:

探险家 CEzreal

盖楼 CGaren

盲僧 CLeesin

无极剑圣 CYi

瑞兹 CRyze

基本思路:

为每个英雄类编写 Attack 、 FightBack 和 Hurted 成员函数。

Attack

FightBack

Hurted

设置基类 CHero ,每个英雄类都继承此基类

1 非多态的实现方法

// 基类
class CHero
{
protected:
int m_nPower ;     // 代表攻击力
int m_nLifeValue ; // 代表生命值
};
// 无极剑圣类
class CYi : public CHero
{
public:
// 攻击盖伦的攻击函数
void Attack(CGaren * pGaren)
{
.... // 表现攻击动作的代码
pGaren->Hurted(m_nPower);
pGaren->FightBack(this);
}
// 攻击瑞兹的攻击函数
void Attack(CRyze * pRyze)
{
.... // 表现攻击动作的代码
pRyze->Hurted(m_nPower);
pRyze->FightBack( this);
}
// 减少自身生命值
void Hurted(int nPower)
{
... // 表现受伤动作的代码
m_nLifeValue -= nPower;
}
// 反击盖伦的反击函数
void FightBack(CGaren * pGaren)
{
....// 表现反击动作的代码
pGaren->Hurted(m_nPower/2);
}
// 反击瑞兹的反击函数
void FightBack(CRyze * pRyze)
{
....// 表现反击动作的代码
pRyze->Hurted(m_nPower/2);
}
};

有 n 种英雄, CYi 类中就会有 n 个 Attack 成员函数,以及 n 个 FightBack成员函数。对于其他类也如此。

如果游戏版本升级,增加了新的英雄寒冰艾希 CAshe ,则程序改动较大。所有的类都需要增加两个成员函数:

void Attack(CAshe * pAshe);
void FightBack(CAshe * pAshe);

这样工作量是非常大的!!非常的不人性,所以这种设计方式是非常的不好!

2 多态的实现方式

用多态的方式去实现,就能得知多态的优势了,那么上面的栗子改成多态的方式如下:

// 基类
class CHero
{
public:
virtual void Attack(CHero *pHero){}
virtual voidFightBack(CHero *pHero){}
virtual void Hurted(int nPower){}
protected:
int m_nPower ;     // 代表攻击力
int m_nLifeValue ; // 代表生命值
};
// 派生类 CYi:
class CYi : public CHero {
public:
// 攻击函数
void Attack(CHero * pHero)
{
.... // 表现攻击动作的代码
pHero->Hurted(m_nPower); // 多态
pHero->FightBack(this);  // 多态
}
// 减少自身生命值
void Hurted(int nPower)
{
... // 表现受伤动作的代码
m_nLifeValue -= nPower;
}
// 反击函数
void FightBack(CHero * pHero)
{
....// 表现反击动作的代码
pHero->Hurted(m_nPower/2); // 多态
}
};

如果增加了新的英雄寒冰艾希 CAshe ,只需要编写新类 CAshe ,不再需要在已有的类里专门为新英雄增加:

void Attack( CAshe * pAshe) ;
void FightBack(CAshe * pAshe) ;

所以已有的类可以原封不动,那么使用多态的特性新增英雄的时候,可见改动量是非常少的。

多态使用方式:

void CYi::Attack(CHero * pHero)
{
pHero->Hurted(m_nPower); // 多态
pHero->FightBack(this);  // 多态
}
CYi yi;
CGaren garen;
CLeesin leesin;
CEzreal ezreal;
yi.Attack( &garen );  //(1)
yi.Attack( &leesin ); //(2)
yi.Attack( &ezreal ); //(3)

根据多态的规则,上面的(1),(2),(3)进入到 CYi::Attack 函数后,分别调用:

CGaren::Hurted
CLeesin::Hurted
CEzreal::Hurted

本页共137段,2606个字符,4195 Byte(字节)